package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ProLinkBusinessEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.LinkFieldDisplayEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkConditionPoJo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.ProLinkBusinessModel;
import com.xbongbong.paas.service.ProLinkBusinessService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.link.business.pojo.LinkBusinessFieldPojo;
import com.xbongbong.pro.link.business.pojo.LinkBusinessListPojo;
import com.xbongbong.pro.link.business.pojo.LinkBusinessSubFieldPojo;
import com.xbongbong.pro.link.business.pojo.dto.LinkBusinessListDTO;
import com.xbongbong.pro.link.business.pojo.dto.LinkBusinessUpdateDTO;
import com.xbongbong.pro.link.business.pojo.vo.LinkBusinessGetVO;
import com.xbongbong.pro.link.business.pojo.vo.LinkBusinessListVO;
import com.xbongbong.pro.link.business.pojo.vo.LinkBusinessUpdateVO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.BusinessFieldEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.help.SaasListHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @version v1.0
 * @date 2019/10/30 15:09
 * @since v1.0
 */
@Service("proLinkBusinessService")
public class ProLinkBusinessServiceImpl implements ProLinkBusinessService {

    private static final Logger LOG = LoggerFactory.getLogger(ProLinkBusinessServiceImpl.class);

    private static final Integer LINK_FIELD_MAX_DISPLAY = 10;
    private static final Integer LINK_SUB_FIELD_MAX_DISPLAY = 5;

    @Resource
    private ProLinkBusinessModel proLinkBusinessModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private SaasListHelp saasListHelp;

    @Override
    public LinkBusinessListVO list(LinkBusinessListDTO linkBusinessListDTO) throws XbbException {
        LinkBusinessListVO linkBusinessListVO = new LinkBusinessListVO();
        try {
            String corpid = linkBusinessListDTO.getCorpid();
            Integer linkBusinessType = linkBusinessListDTO.getLinkBusinessType();
            Integer businessType = linkBusinessListDTO.getBusinessType();
            Long formId = linkBusinessListDTO.getFormId();
            Map<String, Object> param = BeanUtil.convertBean2Map(linkBusinessListDTO, true);
            List<ProLinkBusinessEntity> list = proLinkBusinessModel.findEntitys(param);
            if (Objects.isNull(list)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<Long, ProLinkBusinessEntity> linkBusinessMap = new HashMap<>(list.size());
            list.forEach(item->{
                linkBusinessMap.put(item.getLinkFormId(), item);
            });
            param.clear();
            param.put(StringConstant.CORPID, corpid);
            param.put("businessType", linkBusinessType);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("enable", 1);
            param.put("distributorMark", linkBusinessListDTO.getDistributorMark());
            String attr = linkBusinessListDTO.getAttr();
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), linkBusinessType)) {
                // 除了出库单，暂时没有关联工单的
            } else {
                List<PaasFormEntityExt> formList = paasFormModel.list(param);
                if (Objects.isNull(formList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                List<LinkBusinessListPojo> linkBusinessList = new ArrayList<>();
                List<Long> formIdIn = new ArrayList<>();
                formList.forEach(item->{
                    LinkBusinessListPojo linkBusinessPojo = new LinkBusinessListPojo();
                    linkBusinessPojo.setAttr(attr);
                    linkBusinessPojo.setFormId(formId);
                    linkBusinessPojo.setBusinessType(businessType);
                    linkBusinessPojo.setLinkFormId(item.getId());
                    linkBusinessPojo.setLinkAppId(item.getAppId());
                    linkBusinessPojo.setLinkMenuId(item.getMenuId());
                    linkBusinessPojo.setLinkSaasMark(item.getSaasMark());
                    linkBusinessPojo.setName(item.getName());
                    linkBusinessPojo.setLinkBusinessType(item.getBusinessType());
                    // 设置搜索条件
                    linkBusinessPojo.setConditionList(new ArrayList<>());
                    ProLinkBusinessEntity proLinkBusinessEntity = linkBusinessMap.get(item.getId());
                    if (Objects.nonNull(proLinkBusinessEntity)) {
                        linkBusinessPojo.setId(proLinkBusinessEntity.getId());
                        List<LinkConditionPoJo> conditionList = JSON.parseArray(proLinkBusinessEntity.getCondition(), LinkConditionPoJo.class);
                        linkBusinessPojo.setConditionList(conditionList);
                    }
                    linkBusinessList.add(linkBusinessPojo);
                    formIdIn.add(item.getId());
                });
                param.clear();
                param.put(StringConstant.CORPID, corpid);
                //限制了formId，则不用再限制distributorMark
                param.put("formIdIn", formIdIn);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                List<PaasFormExplainEntity> formExplainList = paasFormExplainModel.findEntitys(param);
                if (Objects.isNull(formExplainList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                Map<Long, List<LinkBusinessFieldPojo>> formExplainMap = new HashMap<>(formExplainList.size());
                List<String> linkedList = BusinessFieldEnum.getByBusinessType(linkBusinessType);
                String linkedText = "";
                if (CollectionsUtil.isNotEmpty(linkedList) && linkedList.size() >= 1) {
                    linkedText = linkedList.get(0);
                }
                String finalLinkedText = linkedText;
                linkedList = saasListHelp.dealFieldList(linkedList, linkBusinessType, businessType, null);
                Boolean isCustomer = Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), linkBusinessType);
                List<String> finalLinkedList = linkedList;
                formExplainList.forEach(item->{
                    List<FieldAttrEntity> explainList = JSON.parseArray(item.getExplains(), FieldAttrEntity.class);
                    ProLinkBusinessEntity proLinkBusinessEntity = linkBusinessMap.get(item.getFormId());
                    Map<String, LinkBusinessFieldPojo> linkBusinessFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    if (Objects.nonNull(proLinkBusinessEntity)) {
                        List<LinkBusinessFieldPojo> fieldList = JSON.parseArray(proLinkBusinessEntity.getField(), LinkBusinessFieldPojo.class);
                        fieldList.forEach(fieldItem->{
                            linkBusinessFieldMap.put(fieldItem.getAttr(), fieldItem);
                        });
                    }
                    List<LinkBusinessFieldPojo> resultList = new ArrayList<>();
                    explainList.stream()
                            // 客户里的公海池退回时间不应该展示在列表
                            .filter(explainItem -> !isCustomer || !Objects.equals(explainItem.getAttr(), CustomerManagementEnum.BACK_PUBLIC_DATE.getAttr()))
                            // 不是列表的字段和没开启的字段不应该被选到
                            .filter(explainItem -> (Objects.equals(1, explainItem.getVisible())
                                    && ShowTypeEnum.listShow(explainItem.getShowType()) && Objects.equals(1, explainItem.getIsOpen())
                                    // 不符合规则的不应该被选到
                                    && Objects.nonNull(LinkFieldDisplayEnum.getFieldTypeEnum(explainItem.getFieldType()))) ||
                                    // bom单里放开成品产品名称
                                    (Objects.equals(XbbRefTypeEnum.BOM_BILL.getCode(), linkBusinessType)
                                            && Objects.equals(BomBillEnum.PRODUCT_NAME_HIDE.getAttr(), explainItem.getAttr()))).forEach(explainItem -> {
                        LinkBusinessFieldPojo linkBusinessFieldPojo = new LinkBusinessFieldPojo();
                        linkBusinessFieldPojo.setAttr(explainItem.getAttr());
                        linkBusinessFieldPojo.setFieldType(explainItem.getFieldType());
                        linkBusinessFieldPojo.setAttrName(explainItem.getAttrName());
                        if (linkBusinessFieldMap.containsKey(explainItem.getAttr())) {
                            // 如果已经设置了字段，直接开启
                            linkBusinessFieldPojo.setEnable(1);
                        } else if (linkBusinessFieldMap.isEmpty() && finalLinkedList.contains(explainItem.getAttr())) {
                            // 如果没有设置任何字段，需要默认一批字段开启
                            linkBusinessFieldPojo.setEnable(1);
                        } else {
                            linkBusinessFieldPojo.setEnable(0);
                        }
                        setSubField(explainItem, linkBusinessFieldPojo, linkBusinessFieldMap);
                        linkBusinessFieldPojo.setEditable(1);
                        if (Objects.equals(explainItem.getAttr(), finalLinkedText)) {
                            linkBusinessFieldPojo.setEditable(0);
                            linkBusinessFieldPojo.setEnable(1);
                        }
                        if (Objects.equals(XbbRefTypeEnum.PURCHASE.getCode(), linkBusinessType)
                                && Objects.equals(XbbRefTypeEnum.PAY_PLAN.getCode(), businessType)
                                && Objects.equals(PurchaseEnum.TOTAL_MONEY.getAttr(), explainItem.getAttr())) {
                            // 付款计划里的采购合同金额，不能去掉，因为有联动关系
                            linkBusinessFieldPojo.setEditable(0);
                            linkBusinessFieldPojo.setEnable(1);
                        } else if (Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), linkBusinessType)
                                && Objects.equals(XbbRefTypeEnum.PAYMENT.getCode(), businessType)
                                && Objects.equals(ContractEnum.AMOUNT.getAttr(), explainItem.getAttr())) {
                            // 应收款里的合同金额，不能去掉，因为有联动关系
                            linkBusinessFieldPojo.setEditable(0);
                            linkBusinessFieldPojo.setEnable(1);
                        } else if (Objects.equals(XbbRefTypeEnum.BOM_BILL.getCode(), linkBusinessType)
                                && Objects.equals(XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), businessType)
                                && Objects.equals(BomBillEnum.VERSION.getAttr(), explainItem.getAttr())) {
                            // 生产单的bom单版本不能去掉，因为有联动关系
                            linkBusinessFieldPojo.setEditable(0);
                            linkBusinessFieldPojo.setEnable(1);
                        }
                        if (Objects.equals(XbbRefTypeEnum.BOM_BILL.getCode(), linkBusinessType)&& Objects.equals(BomBillEnum.PRODUCT_NAME_HIDE.getAttr(), explainItem.getAttr())) {
                            linkBusinessFieldPojo.setAttrName(BomBillEnum.PRODUCT_NAME.getAttrName());
                        }
                        resultList.add(linkBusinessFieldPojo);
                    });
                    formExplainMap.put(item.getFormId(), resultList);
                });
                linkBusinessList.forEach(item->{
                    item.setField(formExplainMap.get(item.getLinkFormId()));
                });
                linkBusinessListVO.setLinkBusinessList(linkBusinessList);
            }

        } catch (Exception e) {
            LOG.error("proLinkBusinessService.list 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return linkBusinessListVO;
    }

    @Override
    public LinkBusinessUpdateVO update(LinkBusinessUpdateDTO linkBusinessUpdateDTO) throws XbbException {
        LinkBusinessUpdateVO linkBusinessUpdateVO = new LinkBusinessUpdateVO();
        try {
            String corpid = linkBusinessUpdateDTO.getCorpid();
            String userId = linkBusinessUpdateDTO.getUserId();
            List<LinkBusinessListPojo> linkBusinessList = linkBusinessUpdateDTO.getLinkBusinessList();
            List<ProLinkBusinessEntity> insertList = new ArrayList<>();
            List<ProLinkBusinessEntity> updateList = new ArrayList<>();
            for (LinkBusinessListPojo item : linkBusinessList) {
                List<LinkBusinessFieldPojo> field = item.getField();
                getEnableFieldList(field);
                validateCondition(item.getConditionList());
                if (Objects.isNull(item.getId())) {
                    ProLinkBusinessEntity proLinkBusinessEntity = new ProLinkBusinessEntity(corpid, item.getAttr(), item.getFormId(), item.getBusinessType(), item.getLinkFormId(), item.getLinkBusinessType());
                    proLinkBusinessEntity.setCondition(JSON.toJSONString(item.getConditionList()));
                    proLinkBusinessEntity.setField(JSON.toJSONString(field));
                    proLinkBusinessEntity.setCorpid(corpid);
                    proLinkBusinessEntity.setCreatorId(userId);
                    long now = DateUtil.getNow();
                    proLinkBusinessEntity.setAddTime(now);
                    proLinkBusinessEntity.setUpdateTime(now);
                    insertList.add(proLinkBusinessEntity);
                } else {
                    ProLinkBusinessEntity proLinkBusinessEntity = new ProLinkBusinessEntity();
                    proLinkBusinessEntity.setId(item.getId());
                    proLinkBusinessEntity.setCorpid(corpid);
                    proLinkBusinessEntity.setCondition(JSON.toJSONString(item.getConditionList()));
                    proLinkBusinessEntity.setField(JSON.toJSONString(field));
                    long now = DateUtil.getNow();
                    proLinkBusinessEntity.setUpdateTime(now);
                    updateList.add(proLinkBusinessEntity);
                }
            }
            if (!insertList.isEmpty()) {
                proLinkBusinessModel.insertBatch(insertList);
            }
            if (!updateList.isEmpty()) {
                proLinkBusinessModel.updateBatch(updateList, corpid);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("proLinkBusinessService.update 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return linkBusinessUpdateVO;
    }

    @Override
    public LinkBusinessGetVO getByLinkFormId(String corpid, String attr, Long formId, Long linkFormId, Integer sourceBusinessType) {
        LinkBusinessGetVO linkBusinessGetVO = new LinkBusinessGetVO();
        List<String> fieldList = new ArrayList<>();
        List<LinkConditionPoJo> conditionList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("linkFormId", linkFormId);
        param.put("formId", formId);
        param.put("attr", attr);
        param.put("businessType", sourceBusinessType);
        List<ProLinkBusinessEntity> proLinkBusinessList = proLinkBusinessModel.findEntitys(param);
        if (CollectionsUtil.isNotEmpty(proLinkBusinessList) && proLinkBusinessList.size() == 1) {
            ProLinkBusinessEntity proLinkBusinessEntity = proLinkBusinessList.get(0);
            List<LinkBusinessFieldPojo> linkBusinessFieldList = JSON.parseArray(proLinkBusinessEntity.getField(), LinkBusinessFieldPojo.class);
            if (CollectionsUtil.isNotEmpty(linkBusinessFieldList)) {
                linkBusinessFieldList.forEach(item->{
                    if (ExplainUtil.isSubForm(item.getFieldType())) {
                        List<LinkBusinessSubFieldPojo> linkBusinessSubFieldList = item.getSubFieldList();
                        if (CollectionsUtil.isNotEmpty(linkBusinessSubFieldList)) {
                            linkBusinessSubFieldList.forEach(subItem->{
                                fieldList.add(item.getAttr() + StringConstant.POINT + subItem.getAttr());
                            });
                        }else{
                            fieldList.add(item.getAttr());
                        }
                    } else {
                        fieldList.add(item.getAttr());
                    }
                });
            }
            conditionList = JSON.parseArray(proLinkBusinessEntity.getCondition(), LinkConditionPoJo.class);
            if (Objects.isNull(conditionList)) {
                conditionList = new ArrayList<>();
            }
        }
        linkBusinessGetVO.setConditionList(conditionList);
        linkBusinessGetVO.setFieldList(fieldList);
        return linkBusinessGetVO;
    }

    /**
     * 校验条件是否一致
     * @param conditionList
     * @throws XbbException
     */
    private void validateCondition(List<LinkConditionPoJo> conditionList) throws XbbException {
        if (CollectionsUtil.isNotEmpty(conditionList)) {
            Set<String> attrSet = new HashSet<>();
            conditionList.forEach(item->{
                attrSet.add(item.getAttr() + StringConstant.POINT + item.getRely());
            });
            Integer size = conditionList.size();
            if (attrSet.size() != size) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.CONDITION_SAME);
            }
        }
    }
    /**
     * 获取需要显示的字段
     * @param field
     */
    private void getEnableFieldList(List<LinkBusinessFieldPojo> field) throws XbbException {
        if (CollectionsUtil.isEmpty(field)) {
            return;
        }
        Iterator<LinkBusinessFieldPojo> iterator = field.iterator();
        while (iterator.hasNext()) {
            LinkBusinessFieldPojo linkBusinessFieldPojo = iterator.next();
            if (Objects.equals(0, linkBusinessFieldPojo.getEnable())) {
                iterator.remove();
                continue;
            }
            List<LinkBusinessSubFieldPojo> subFieldList = linkBusinessFieldPojo.getSubFieldList();
            if (CollectionsUtil.isNotEmpty(subFieldList)) {
                Iterator<LinkBusinessSubFieldPojo> subFieldPojoIterator = subFieldList.iterator();
                while (subFieldPojoIterator.hasNext()) {
                    LinkBusinessSubFieldPojo linkBusinessSubFieldPojo = subFieldPojoIterator.next();
                    if (Objects.equals(0, linkBusinessSubFieldPojo.getEnable())) {
                        subFieldPojoIterator.remove();
                        continue;
                    }
                }
                if (subFieldList.size() > LINK_SUB_FIELD_MAX_DISPLAY) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.SUB_FORM_LINK_DISPLAY_MAX_LARGE);
                }
            }
        }
        if (field.size() > LINK_FIELD_MAX_DISPLAY) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_LINK_DISPLAY_MAX_LARGE);
        }
    }

    /**
     * 设置子表单显示字段
     * @param explainItem
     * @param result
     * @param linkBusinessFieldMap
     */
    private void setSubField(FieldAttrEntity explainItem, LinkBusinessFieldPojo result, Map<String, LinkBusinessFieldPojo> linkBusinessFieldMap) {
        if (ExplainUtil.isSubForm(explainItem.getFieldType())) {
            LinkBusinessFieldPojo linkBusinessFieldPojo = linkBusinessFieldMap.get(explainItem.getAttr());
            Map<String, LinkBusinessSubFieldPojo> linkBusinessSubFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.nonNull(linkBusinessFieldPojo)) {
                List<LinkBusinessSubFieldPojo> subFieldList = linkBusinessFieldPojo.getSubFieldList();
                subFieldList.forEach(fieldItem->{
                    linkBusinessSubFieldMap.put(fieldItem.getAttr(), fieldItem);
                });
            }
            List<? extends FieldAttrEntity> subExplain = explainItem.getSubForm().getItems();
            List<LinkBusinessSubFieldPojo> subFieldResultList = new ArrayList<>();
            subExplain.forEach(subItem->{
                if (Objects.equals(1, subItem.getVisible())
                        && Objects.nonNull(LinkFieldDisplayEnum.getFieldTypeEnum(subItem.getFieldType()))) {
                    LinkBusinessSubFieldPojo linkBusinessSubFieldPojo = new LinkBusinessSubFieldPojo();
                    linkBusinessSubFieldPojo.setAttr(subItem.getAttr());
                    linkBusinessSubFieldPojo.setFieldType(subItem.getFieldType());
                    linkBusinessSubFieldPojo.setAttrName(subItem.getAttrName());
                    if (linkBusinessSubFieldMap.containsKey(subItem.getAttr())) {
                        linkBusinessSubFieldPojo.setEnable(1);
                    } else {
                        linkBusinessSubFieldPojo.setEnable(0);
                    }
                    linkBusinessSubFieldPojo.setEditable(1);
                    subFieldResultList.add(linkBusinessSubFieldPojo);
                }
            });
            result.setSubFieldList(subFieldResultList);
        }
    }

}
